﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Configuration;

namespace Fcdbas.Core.WCF
{
    /// <summary>
    /// 远程服务工厂
    /// </summary>
    public static class ServiceFactory
    {
        //private static Hashtable _channels;

        //static ServiceFactory()
        //{
        //    _channels = new Hashtable();
        //}
        /// <summary>
        /// Method creates a connection to Service based on the interface passed
        /// by the user. it uses the channel factory to open the service.
        /// 
        /// Tested the synchronization if multiple calls to the same service.
        /// </summary>
        /// <typeparam name="I">Service interface</typeparam>
        /// <returns></returns>
        public static I CreateInstance<I>() where I : class
        {

            string endPointConfig = typeof(I).Name.ToString();

            //lock (_channels.SyncRoot)
            //{
            //    if (_channels.ContainsKey(endPointConfig) == false)
            //    {
            //        _channels.Add(endPointConfig, OpenChannel<I>());
            //    }
            //    else if (((((IClientChannel)_channels[endPointConfig]).State == CommunicationState.Faulted)) || (((IClientChannel)_channels[endPointConfig]).State == CommunicationState.Closed) || (((IClientChannel)_channels[endPointConfig]).State == CommunicationState.Closing))
            //    {
            //        //If the channel is faulted. The existing channel will be removed from the cache
            //        //and recreate the channel again.
            //        ((IClientChannel)_channels[endPointConfig]).Abort();
            //        ((IClientChannel)_channels[endPointConfig]).Close();
            //        _channels.Remove(endPointConfig);
            //        _channels.Add(endPointConfig, OpenChannel<I>());
            //    }
            //    return _channels[endPointConfig] as I;
            //}
            return (I)(new ServiceRealProxy<I>(endPointConfig).GetTransparentProxy());

        }
        /// <summary>
        /// 创建通过终接点配置和远程地址的实例
        /// </summary>
        /// <typeparam name="I"></typeparam>
        /// <param name="remoteAddress"></param>
        /// <returns></returns>
        public static I CreateInstance<I>(string remoteAddress) where I : class
        {
            string endPointConfig = typeof(I).Name.ToString();

           
            return (I)(new ServiceRealProxy<I>(endPointConfig,remoteAddress).GetTransparentProxy());
        }
        public static void CloseProxy<I>(I instance) where I : class
        {
           // ICommunicationObject proxy = instance as ICommunicationObject;
           // if (proxy != null)
            //    proxy.Close();
        }
        /// <summary>
        /// Method to create the channel to the service.
        /// </summary>
        /// <typeparam name="I">Service Contract</typeparam>
        /// <returns>Channel to the service</returns>
        private static I OpenChannel<I>() where I : class
        {
            string endPointConfig = typeof(I).Name.ToString();
            ChannelFactory<I> factory = new ChannelFactory<I>(endPointConfig);
          //  factory.Endpoint.Behaviors.Add(new WebHttpBehavior());

            factory.Open();
            I channel = factory.CreateChannel();
            ((IClientChannel)channel).Faulted += new EventHandler(ServiceFactory_Faulted);
            return channel;
        }

        static void ServiceFactory_Faulted(object sender, EventArgs e)
        {
            ((ICommunicationObject)sender).Abort();
            ((ICommunicationObject)sender).Close();
            //Type typ = ((ICommunicationObject)sender).GetType();
            //lock (_channels.SyncRoot)
            //{
            //    ((ICommunicationObject)sender).Faulted -= new EventHandler(ServiceFactory_Faulted);
            //    _channels.Remove(typ.Name);
            //}
        }
    }
}
